import "package:flutter/material.dart";
import "dart:async";

// 轮播图
class Swiper extends StatefulWidget {
  final double height; //高度
  final int currentIndex; //当前显示下标
  final List<Widget> children; //轮播图元素
  final bool isFade; //是否淡入淡出
  final bool showIndicator; //是否显示指示器
  final Alignment indicatorAlignment; //指示器方位
  final MainAxisAlignment indicatorMainAxisAlignment; //指示器主轴
  final double indicatorRadius; //指示器半径
  final Axis indicatorRadiusDirection; //指示器排序方向
  final Color indicatorInactiveColor; //指示器未选中颜色
  final Color indicatorActiveColor; //指示器选中颜色
  final bool loop; //是否循环
  final bool auto; //是否自动切换
  final Duration duration; //自定切换间隔
  final Duration animatedDuration;
  final Function(int) onCurrentIndexChange; //下标改变后触发事件
  const Swiper({
    super.key,
    required this.height,
    this.currentIndex = 0,
    required this.onCurrentIndexChange,
    required this.children,
    this.isFade = false,
    this.showIndicator = false,
    this.indicatorAlignment = Alignment.bottomCenter,
    this.indicatorMainAxisAlignment = MainAxisAlignment.end,
    this.indicatorRadius = 5,
    this.indicatorInactiveColor = const Color.fromARGB(107, 255, 255, 255),
    this.indicatorActiveColor = Colors.white,
    this.indicatorRadiusDirection = Axis.horizontal,
    this.loop = true,
    this.auto = false,
    this.duration = const Duration(seconds: 2),
    this.animatedDuration = const Duration(milliseconds: 500),
  });
  @override
  State<StatefulWidget> createState() {
    return _SwiperState();
  }
}

class _SwiperState extends State<Swiper> {
  late PageView pageView;
  late PageController pageController;
  late NotificationListener<ScrollNotification> notificationListener;
  int currentValue = 0; //当前虚拟下标（widget.items下的坐标）
  int realCurrentValue = 0; //当前真实下标（整个pageView的下标）
  double lastPageControllerPage = 0; //控制器上次page值
  int? jumpToPageTarget; //跳转页下标
  String pageControllerDirection = ''; //当前控制器滚动方向
  bool listening = false; //是否正在监听滚动结束
  Timer? timer; //滚动定时器
  GlobalKey globalKey = GlobalKey<_SwiperState>();
  // Duration animatedDuration = const Duration(milliseconds: 500); //切换动画时间
  Curve animatedCurves = Curves.linear;

  @override
  void initState() {
    if (!widget.loop || widget.children.length == 1) {
      realCurrentValue = 0;
    } else {
      realCurrentValue = 1;
      lastPageControllerPage = 1; //同步初始值
    }
    pageController = PageController(initialPage: realCurrentValue);
    // 监听事件
    pageController.addListener(() {
      // print(pageController.page);
      double _page = pageController.page ?? 0;
      if (_page < lastPageControllerPage) {
        // 如果当前page小于上一次page，说明是左滑
        pageControllerDirection = 'left';
      } else {
        pageControllerDirection = 'right';
      }
      setState(() {
        lastPageControllerPage = _page;
      });
    });
    // initPageView();
    // 只有循环且 自动切换开启定时器
    if (widget.loop && widget.auto) createListenTimer();
    super.initState();
  }

  void initPageView() {
    // 不循环或者只有一个内容时
    if (!widget.loop || widget.children.length == 1) {
      pageView = PageView(
        controller: pageController,
        children: widget.children,
        onPageChanged: (value) {
          setState(() {
            currentValue = value;
            realCurrentValue = value;
          });
        },
      );
    } else {
      // 当items.length >1，取开始元素插入最后，取末尾元素插入开始
      List<Widget> items = [...widget.children];
      var startItem = widget.children[0];
      var endItem = widget.children[widget.children.length - 1];
      items.insert(0, endItem);
      items.add(startItem);

      List<SwiperFadeItem> children = [];
      if (widget.isFade) {
        for (int i = 0; i < items.length; i++) {
          children.add(SwiperFadeItem(
            itemPage: i,
            controllerPage: lastPageControllerPage,
            currentPage: realCurrentValue,
            child: items[i],
          ));
        }
      }
      // 此时
      pageView = PageView(
        controller: pageController,
        children: widget.isFade ? children : items,
        onPageChanged: (value) {
          // print('[onPageChanged]:$value');
          // 实际上会多出两个元素，需要重新赋值
          // [Cl(A3)],[A1],[A2],[A3],[Cr(A1)]
          // 总数为5，当处于Cl，跳到A3；当处于Cr,跳到A1
          late int _value; //虚拟的下标
          if (value >= items.length - 1) {
            // 处于Cr
            _value = 0;
            jumpToPageTarget = 1; //跳到A1
          } else if (value == 0) {
            // 处于Cl
            _value = items.length - 3;
            jumpToPageTarget = items.length - 2; //跳到A3
          } else {
            _value = value - 1;
            jumpToPageTarget = null;
          }
          widget.onCurrentIndexChange(_value);
          setState(() {
            currentValue = _value;
            realCurrentValue = value;
          });
        },
      );
    }
  }

  void createListenTimer() {
    cancelListenTimer();
    timer = Timer.periodic(widget.duration, (time) {
      setState(() {
        realCurrentValue++;
        // print('[定时器执行]:$realCurrentValue');
      });
      pageController.animateToPage(
        realCurrentValue,
        duration: widget.animatedDuration,
        curve: animatedCurves,
      );
    });
  }

  void cancelListenTimer() {
    if (timer == null) return;
    // 清除定时器
    timer?.cancel();
    timer = null;
  }

  @override
  void dispose() {
    pageController.dispose();
    timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    initPageView();
    List<Widget> indicator = [];
    for (int i = 0; i < widget.children.length; i++) {
      indicator.add(Container(
        width: widget.indicatorRadius,
        height: widget.indicatorRadius,
        margin: const EdgeInsets.only(left: 4),
        decoration: BoxDecoration(
          color: i == currentValue
              ? widget.indicatorActiveColor
              : widget.indicatorInactiveColor,
          borderRadius: BorderRadius.circular(widget.indicatorRadius / 2),
        ),
      ));
    }

    notificationListener = NotificationListener<ScrollNotification>(
      child: widget.showIndicator
          ? Stack(
              children: [
                pageView,
                Align(
                  alignment: widget.indicatorAlignment,
                  child: SizedBox(
                    width: double.infinity,
                    child: Padding(
                      padding: const EdgeInsets.all(8),
                      child: Flex(
                        direction: widget.indicatorRadiusDirection,
                        mainAxisAlignment: widget.indicatorMainAxisAlignment,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: indicator,
                      ),
                    ),
                  ),
                ),
              ],
            )
          : pageView,
      onNotification: (notification) {
        if (notification is ScrollStartNotification) {
          listening = true;
        } else if (notification is ScrollEndNotification) {
          if (listening) {
            listening = false;
            // print('将跳转页面下标：$jumpToPageTarget');
            if (jumpToPageTarget != null) {
              pageController.jumpToPage(jumpToPageTarget as int);
              setState(() {
                jumpToPageTarget = null;
              });
            }
            if (widget.auto && widget.loop) createListenTimer();
          }
        } else if (notification is ScrollUpdateNotification) {
          // 如果正在滚动，则停止监听
          cancelListenTimer();
        }
        return false;
      },
    );

    return Container(
      width: double.infinity,
      height: widget.height,
      decoration: const BoxDecoration(
        color: Color(0xfff4f5fa),
      ),
      child: notificationListener,
    );
  }
}

class SwiperFadeItem extends StatefulWidget {
  final double startOpacity; //开始透明度（显示）
  final double endOpacity; //结束透明度（隐藏）
  final double controllerPage; //控制器页
  final int currentPage; //当前页
  final int itemPage; //元素所在页
  final Widget child;
  const SwiperFadeItem({
    super.key,
    this.startOpacity = 1,
    this.endOpacity = 0,
    required this.itemPage,
    required this.controllerPage,
    required this.currentPage,
    required this.child,
  });
  @override
  State<StatefulWidget> createState() {
    return _SwiperFadeItemState();
  }
}

class _SwiperFadeItemState extends State<SwiperFadeItem> {
  String status = ''; //当前状态 in / out / ''
  double opacity = 1;
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // currentPage 是即时改变，而动画切换后改变
    // 当1->2时，itemPage是1，currentPage是2，controllerPage由1->2

    // 从而得知 itemPage=currentPage±1（currentPage>itemPage，则是右滑动，否则左滑动），则itemPage为离开页，透明度1->0
    // itemPage=currentPage，则itemPage为进入，透明度0->1
    if (widget.itemPage == widget.currentPage) {
      status = 'in';
      // 1.1 1.2 1.3... 2 - 2 = 0.9 0.8 0.7... 0
      // 0.1 0.2 0.3... 1
      opacity = double.parse(
          (1 - (widget.controllerPage - widget.currentPage).abs())
              .toStringAsFixed(2));
    } else if (widget.itemPage < widget.currentPage &&
        widget.itemPage == widget.currentPage - 1) {
      // 右滑动离开
      status = 'out';
      opacity = double.parse((widget.controllerPage - widget.currentPage)
          .abs()
          .toStringAsFixed(2));
    } else if (widget.itemPage > widget.currentPage &&
        widget.itemPage == widget.currentPage + 1) {
      // 左滑动离开
      status = 'out';
      opacity = double.parse((widget.controllerPage - widget.currentPage)
          .abs()
          .toStringAsFixed(2));
    }
    opacity = opacity <= 0 ? 0 : opacity;
    opacity = opacity >= 1 ? 1 : opacity;

    return Opacity(
      opacity: opacity,
      // child: Text(
      //     '元素所在${widget.itemPage}页  /  实际当前页${widget.currentPage} / 当前状态$status / 当前透明度$opacity'),
      child: widget.child,
    );
  }
}
